Skip to content

feat(llm-docs): add the platform module for bundled on-disk docs - #15242

Draft
midleman wants to merge 16 commits into
mainfrom
mi/bundle-docs-2a
Draft

feat(llm-docs): add the platform module for bundled on-disk docs#15242
midleman wants to merge 16 commits into
mainfrom
mi/bundle-docs-2a

Conversation

@midleman

@midleman midleman commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Step 2a of the bundled on-disk docs work: a host-agnostic platform/positronDocs module that downloads, verifies, caches, and serves the slim LLM docs bundle so the assistant can read docs from disk instead of fetching positron.posit.co. All I/O goes through three injected interfaces (HTTP, file store, archive), so the state machine is unit-testable with no DI container and no node imports.

  • positronDocsBundle.ts -- types, URL resolution, bundle.json and checksum-file parsing
  • positronDocsIO.ts -- the three I/O interfaces plus the ILocalDocs result shape
  • positronDocsValidate.ts -- zip-entry traversal guard and extracted-bundle validation
  • positronDocsCache.ts -- the orchestrator: install, version convergence, single-flight, hard-failure throttling
  • 85 Vitest cases; 95% branch coverage on the orchestrator

Nothing is wired up here -- no registration, no instantiation, unreachable at runtime until the next PR adds the extension-host service. That PR must not merge before this one.

Release Notes

New Features

  • N/A

Bug Fixes

  • N/A

Validation Steps

Unit tests added:

npx vitest run src/vs/platform/positronDocs/

Two things worth a reviewer's attention:

  • _writeState and cleanup deletes deliberately swallow their errors. The disk failures that break them are the same ones that break a download, so throwing would withdraw a valid cached bundle and violate the governing rule that a valid cache is always served.
  • Release builds fetch their exact version and fall back to the mutable alias until it publishes, re-checking every launch. That convergence check is intentionally never throttled; only hard failures are.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

E2E Tests 🚀
This PR will run tests tagged with: @:critical

Note

No feature tags detected. If this PR needs feature coverage, add the tag above and retrigger the workflow.

readme  valid tags

@midleman midleman changed the title feat: add the platform module for bundled on-disk docs feat(llm-docs): add the platform module for bundled on-disk docs Jul 31, 2026
@midleman
midleman force-pushed the mi/bundle-docs-2a branch from 5423e4f to b70a80d Compare July 31, 2026 13:01
midleman added 16 commits July 31, 2026 09:27
- Add IDocsFileStore.isDirectory and use it in countFiles. Inferring
  file-ness from an empty readdir counted an empty directory as a file,
  which real extractors can produce, and relied on behaviour a node-backed
  store does not have (it throws ENOTDIR on a file).
- Make _prune best-effort. A readdir or unlink failure threw out of
  ensure() and discarded an install that was already on disk.
- Track a generation counter so invalidate() called mid-fetch is not
  overwritten by the completing attempt re-arming the session gate.
- Log an unexpected HEAD status on the convergence check; 404 stays quiet.
- Drop all-slashes segments in joinDocsPath, which left a trailing slash.
- Encode the fake zip as JSON so entry contents cannot mis-split.
- Assert state content after a 304, add empty-directory and mid-flight
  invalidate coverage, and cover joinDocsPath.
The cap exists to bound a write the digest cannot vet until the bytes have
landed, not to express an expected bundle size. Since it ships baked into a
client while the bundle publishes separately, a client that trips it falls
back to web docs with no way to fix it after the fact. The publish pipeline
now enforces the real size budget.
…tate

Each rejection case now asserts the reason it was refused, so a case can no
longer pass on a different failure than the one it names. Adds coverage for a
state file pointing at a deleted version directory and for an unparseable
state file, and replaces a test that asserted on the shape of the logger fake
with one that asserts the level each outcome kind logs at.
"Ports" collides with base/common/ports.ts and base/node/ports.ts, which are
about TCP ports, and the module does HTTP - so the name invites the wrong
reading. "Sidecar" now reads as the container pattern more than the companion
file it means here; "checksum file" says the same thing plainly and pairs with
the digest it holds.
At install time the previous state.json already names the one directory
being superseded, so delete it by name instead of sweeping the cache
root. This removes the mtime guard, the DOCS_PRUNE_IDLE_MS constant, and
the mtime port method, and closes the cross-window hazard by removing
the scan that caused it. Crash debris is no longer collected; it is
bounded by crash count and judged not worth the machinery (design doc
revision 11).
The only 'artefact' left in src/vs; 37 files already use 'artifact'.
@midleman
midleman force-pushed the mi/bundle-docs-2a branch from dbec324 to 3f7eb82 Compare July 31, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant